#ifndef __PSSEARCH_H__
#define __PSSEARCH_H__

#include "data.h"
#include "psTypes.h"
#include "psUtil.h"

//const int INF = 99999;
const int INVALID = -9999;
const int epsilon = 0;

const int TAG_DATA            = 0;
const int TAG_ALL_COLOR_SIZE  = 1;
const int TAG_MIN_COST        = 2;
const int TAG_GRP_COST_MATRIX = 3;
const int TAG_IND_COST_MATRIX = 4;
const int TAG_NUM_LOW_COST    = 5;

typedef struct colorPairs {
	int x;
	int y;
}ColorPairs;

class PSSearch {
public:
	PSSearch(Data &dataObj, ArgStruct &args, int size, int rank);
	~PSSearch();

	std::vector<intIntVec> getColorAssignments();

	double partitionSendReceive(std::vector<intIntVec> allAssignments, int size); // Master
	bool calcAndSend(int rank); // Worker 
	std::vector<intIntVec> genAllColoring();
	void genColoring(int t, int colors[]);

private:
	static int spaceDim;
	std::vector<intVec> s;
	std::vector<intVec> data;
	std::vector<intIntVec> colorAssignments;

	int nInds;
	int nSteps;

	int alpha;
	int beta1;
	int beta2;
	int gamma;

	int maxColor;

	int size; // No. of MPI processes
	int myRank;
	int partitionSize;
	intMatrixType sigmaT;
	intVec colorSet;
	std::vector<ColorPairs> allColorPairs;
	std::vector<int> colors;

	MPI::Datatype MPI_IntVec;
	MPI::Datatype MPI_IntMat;
	MPI::Datatype MPI_IntCube;

	intMatrixType costMatrix;
  
        // Private methods

	int ind(int x, int y);
	int grp(int t, int x);
	int col(std::vector<int> &R, int x);

	void initializeCosts();
	std::vector<int> getSigmaG(int t);
	int PI(int t, std::vector<int> &S, int x, std::vector<int> indRow);
	int getCost(std::vector<intVec> mat);
	intIntVec getIndColoring(intIntVec coloring);
	intIntVec getPhiI(intIntVec phiI, intVec S);
	void receiveComputedData();
	void setSigmaT(intMatrixType coloring);
	std::vector<ColorPairs> getColorPairs();
	int computeLowerBound(int i, int t, int fgt);

	// Inline methods
	inline int f(int ind, int t) {
                // color of group 'g' at time 't'
//		return coloring[ind][t];
	}

	inline int rotateColors(int colorVector[]) {
		int temp = colorVector[0];
		for (int i = 0; i < this->maxColor - 1; i++) 
			colorVector[i] = colorVector[i + 1];

		colorVector[this->maxColor - 1] = temp;
	}
};

#endif
